﻿using LeRenard.Libraries.PlatformInspection.InfoNodes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;

namespace LeRenard.Libraries.PlatformInspection.Inspectors.Network
{
    public class NetworkInterfacesNetworkInspectorModule : InspectorModule<NetworkInspector>
    {
        /// <summary>
        /// Constructions
        /// </summary>
        public NetworkInterfacesNetworkInspectorModule() 
            : base("Network Interfaces") 
        { 
        }

        /// <summary>
        /// Gets the information this module gathers.
        /// </summary>        
        protected override IEnumerable<InfoNode> GetInformationImpl()
        {
            var infoNodes = new List<InfoNode>();            

            foreach (var networkInterface in NetworkInterface.GetAllNetworkInterfaces())
            {
                var networkInterfaceNode = new InfoNode(
                    networkInterface.Name,                    
                    displayStrategy: InfoNodeEmptyValueDisplayStrategy.TreatAsNormalInfoNodeWithoutValue
                );
                infoNodes.Add(networkInterfaceNode);

                networkInterfaceNode.AddInfoNode(
                    name: "Id",
                    value: networkInterface.Id,
                    displayStrategy: InfoNodeEmptyValueDisplayStrategy.TreatAsNormalInfoNode
                );

                networkInterfaceNode.AddInfoNode(
                    name: "Description", 
                    value: networkInterface.Description,
                    displayStrategy: InfoNodeEmptyValueDisplayStrategy.TreatAsNormalInfoNode
                );

                networkInterfaceNode.AddInfoNode(
                    name: "Type",
                    value: networkInterface.NetworkInterfaceType.ToString(),
                    displayStrategy: InfoNodeEmptyValueDisplayStrategy.TreatAsNormalInfoNode
                );

                networkInterfaceNode.AddInfoNode(
                    name: "Status",
                    value: networkInterface.OperationalStatus.ToString(),
                    displayStrategy: InfoNodeEmptyValueDisplayStrategy.TreatAsNormalInfoNode
                );

                var ipNode = new InfoNode(
                    name: "IP Address(es)",
                    displayStrategy: InfoNodeEmptyValueDisplayStrategy.TreatAsTitleInfoNode
                );
                networkInterfaceNode.AddInfoNode(ipNode);
                foreach (UnicastIPAddressInformation ip in networkInterface.GetIPProperties().UnicastAddresses)
                {
                    ipNode.AddInfoNode(
                        name: ip.Address.ToString(),                        
                        displayStrategy: InfoNodeEmptyValueDisplayStrategy.TreatAsNormalInfoNodeWithoutValue
                    );
                }

                var dnsNode = new InfoNode(
                    name: "DNS Host(s)",
                    displayStrategy: InfoNodeEmptyValueDisplayStrategy.TreatAsTitleInfoNode
                );
                networkInterfaceNode.AddInfoNode(dnsNode);
                foreach (IPAddress ip in networkInterface.GetIPProperties().DnsAddresses)
                {
                    var hostName = "";
                    try { hostName = Dns.GetHostEntry(ip).HostName; }
                    catch (Exception ex) { }

                    dnsNode.AddInfoNode(
                        name: ip.ToString(),
                        value: hostName,
                        displayStrategy: String.IsNullOrEmpty(hostName) ? 
                            InfoNodeEmptyValueDisplayStrategy.TreatAsNormalInfoNode :
                            InfoNodeEmptyValueDisplayStrategy.TreatAsNormalInfoNodeWithoutValue
                    );
                }
            }                

            return infoNodes.OrderBy(inf => inf.Name);
        }
    }
}
